home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / CONTRIB / FRACTALS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-08-12  |  18.0 KB  |  714 lines

  1. /*
  2.  * To compile: cc -o fractals fractals.c -lGL -lGLU -lX11 -lglut -lXmu -lm
  3.  *
  4.  * Usage: fractals
  5.  *
  6.  * Homework 6, Part 2: fractal mountains and fractal trees 
  7.  * (Pretty Late)
  8.  *
  9.  * Draws fractal mountains and trees -- and an island of mountains in water 
  10.  * (I tried having trees on the island but it didn't work too well.)
  11.  *
  12.  * Two viewer modes: polar and flying (both restrained to y>0 for up vector).
  13.  * Keyboard 0->9 and +/- control speed when flying.
  14.  *
  15.  * Only keyboard commands are 0-9 and +/- for speed in flying mode.
  16.  *
  17.  * Fog would make the island look much better, but I couldn't get it to work
  18.  * correctly.  Would line up on -z axis not from eye.
  19.  *
  20.  * Philip Winston - 3/4/95
  21.  * pwinston@hmc.edu
  22.  * http://www.cs.hmc.edu/people/pwinston
  23.  *
  24.  */
  25.  
  26. #include <GL/glut.h>
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <math.h>
  31. #include <limits.h>           /* ULONG_MAX is defined here */
  32. #include <float.h>            /* FLT_MAX is atleast defined here */
  33.  
  34. #include <time.h>  /* for random seed */
  35.  
  36. #include "fracviewer.h"
  37.  
  38. #ifdef _WIN32
  39. #define drand48() (((float) rand())/((float) RAND_MAX))
  40. #define srand48(x) (srand((x)))
  41. #endif
  42.  
  43. typedef enum { NOTALLOWED, MOUNTAIN, TREE, ISLAND, BIGMTN, STEM, LEAF, 
  44.                MOUNTAIN_MAT, WATER_MAT, LEAF_MAT, TREE_MAT, STEMANDLEAVES,
  45.                AXES } DisplayLists;
  46.  
  47. #define MAXLEVEL 8
  48.  
  49. int Rebuild = 1,        /* Rebuild display list in next display? */
  50.     Fract   = TREE,     /* What fractal are we building */
  51.     Level   = 4;        /* levels of recursion for fractals */     
  52.  
  53. int DrawAxes = 0;       
  54.  
  55. /***************************************************************/
  56. /************************* VECTOR JUNK *************************/
  57. /***************************************************************/
  58.  
  59.   /* print vertex to stderr */
  60. void printvert(float v[3])
  61. {
  62.   fprintf(stderr, "(%f, %f, %f)\n", v[0], v[1], v[2]);
  63. }
  64.  
  65.   /* normalizes v */
  66. void normalize(GLfloat v[3])
  67. {
  68.   GLfloat d = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
  69.  
  70.   if (d == 0)
  71.     fprintf(stderr, "Zero length vector in normalize\n");
  72.   else
  73.     v[0] /= d; v[1] /= d; v[2] /= d;
  74. }
  75.  
  76.   /* calculates a normalized crossproduct to v1, v2 */
  77. void ncrossprod(float v1[3], float v2[3], float cp[3])
  78. {
  79.   cp[0] = v1[1]*v2[2] - v1[2]*v2[1];
  80.   cp[1] = v1[2]*v2[0] - v1[0]*v2[2];
  81.   cp[2] = v1[0]*v2[1] - v1[1]*v2[0];
  82.   normalize(cp);
  83. }
  84.  
  85.   /* calculates normal to the triangle designated by v1, v2, v3 */
  86. void triagnormal(float v1[3], float v2[3], float v3[3], float norm[3])
  87. {
  88.   float vec1[3], vec2[3];
  89.  
  90.   vec1[0] = v3[0] - v1[0];  vec2[0] = v2[0] - v1[0];
  91.   vec1[1] = v3[1] - v1[1];  vec2[1] = v2[1] - v1[1];
  92.   vec1[2] = v3[2] - v1[2];  vec2[2] = v2[2] - v1[2];
  93.  
  94.   ncrossprod(vec2, vec1, norm);
  95. }
  96.  
  97. float xzlength(float v1[3], float v2[3])
  98. {
  99.   return sqrt((v1[0] - v2[0])*(v1[0] - v2[0]) +
  100.               (v1[2] - v2[2])*(v1[2] - v2[2]));
  101. }
  102.  
  103. float xzslope(float v1[3], float v2[3])
  104. {
  105.   return ((v1[0] != v2[0]) ? ((v1[2] - v2[2]) / (v1[0] - v2[0]))
  106.                        : FLT_MAX);
  107. }
  108.  
  109.  
  110. /***************************************************************/
  111. /************************ MOUNTAIN STUFF ***********************/
  112. /***************************************************************/
  113.  
  114. GLfloat DispFactor[MAXLEVEL];  /* Array of what to multiply random number
  115.                   by for a given level to get midpoint
  116.                   displacement  */
  117. GLfloat DispBias[MAXLEVEL];  /* Array of what to add to random number
  118.                 before multiplying it by DispFactor */
  119.  
  120. #define NUMRANDS 191
  121. float RandTable[NUMRANDS];  /* hash table of random numbers so we can
  122.                    raise the same midpoints by the same amount */ 
  123.  
  124.          /* The following are for permitting an edge of a moutain to be   */
  125.          /* pegged so it won't be displaced up or down.  This makes it    */
  126.          /* easier to setup scenes and makes a single moutain look better */
  127.  
  128. GLfloat Verts[3][3],    /* Vertices of outside edges of mountain */
  129.         Slopes[3];      /* Slopes between these outside edges */
  130. int     Pegged[3];      /* Is this edge pegged or not */           
  131.  
  132.  /*
  133.   * Comes up with a new table of random numbers [0,1)
  134.   */
  135. void InitRandTable(unsigned int seed)
  136. {
  137.   int i;
  138.  
  139.   srand48((long) seed);
  140.   for (i = 0; i < NUMRANDS; i++)
  141.     RandTable[i] = drand48() - 0.5;
  142. }
  143.  
  144.   /* calculate midpoint and displace it if required */
  145. void Midpoint(GLfloat mid[3], GLfloat v1[3], GLfloat v2[3],
  146.           int edge, int level)
  147. {
  148.   unsigned hash;
  149.  
  150.   mid[0] = (v1[0] + v2[0]) / 2;
  151.   mid[1] = (v1[1] + v2[1]) / 2;
  152.   mid[2] = (v1[2] + v2[2]) / 2;
  153.   if (!Pegged[edge] || (fabs(xzslope(Verts[edge], mid) 
  154.                         - Slopes[edge]) > 0.00001)) {
  155.     srand48((int)((v1[0]+v2[0])*23344));
  156.     hash = drand48() * 7334334;
  157.     srand48((int)((v2[2]+v1[2])*43433));
  158.     hash = (unsigned)(drand48() * 634344 + hash) % NUMRANDS;
  159.     mid[1] += ((RandTable[hash] + DispBias[level]) * DispFactor[level]);
  160.   }
  161. }
  162.  
  163.   /*
  164.    * Recursive moutain drawing routine -- from lecture with addition of 
  165.    * allowing an edge to be pegged.  This function requires the above
  166.    * globals to be set, as well as the Level global for fractal level 
  167.    */
  168. void FMR(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3], int level)
  169. {
  170.   if (level == Level) {
  171.     GLfloat norm[3];
  172.  
  173.     triagnormal(v1, v2, v3, norm);
  174.     glNormal3fv(norm);
  175.     glVertex3fv(v1);
  176.     glVertex3fv(v2);
  177.     glVertex3fv(v3);
  178.  
  179.   } else {
  180.     GLfloat m1[3], m2[3], m3[3];
  181.  
  182.     Midpoint(m1, v1, v2, 0, level);
  183.     Midpoint(m2, v2, v3, 1, level);
  184.     Midpoint(m3, v3, v1, 2, level);
  185.  
  186.     FMR(v1, m1, m3, level + 1);
  187.     FMR(m1, v2, m2, level + 1);
  188.     FMR(m3, m2, v3, level + 1);
  189.     FMR(m1, m2, m3, level + 1);
  190.   }
  191. }
  192.  
  193.  /*
  194.   * sets up lookup tables and calls recursive mountain function
  195.   */
  196. void FractalMountain(GLfloat v1[3], GLfloat v2[3], GLfloat v3[3],
  197.                      int pegged[3])
  198. {
  199.   GLfloat lengths[MAXLEVEL];
  200.   GLfloat fraction[8] = { 0.3, 0.3, 0.4, 0.2, 0.3, 0.2, 0.4, 0.4  };
  201.   GLfloat bias[8]     = { 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1  };
  202.   int i;
  203.   float avglen = (xzlength(v1, v2) + 
  204.                   xzlength(v2, v3) +
  205.           xzlength(v3, v1) / 3);
  206.  
  207.   for (i = 0; i < 3; i++) {
  208.     Verts[0][i] = v1[i];      /* set mountain vertex globals */
  209.     Verts[1][i] = v2[i];
  210.     Verts[2][i] = v3[i];
  211.     Pegged[i] = pegged[i];
  212.   }
  213.  
  214.   Slopes[0] = xzslope(Verts[0], Verts[1]);   /* set edge slope globals */
  215.   Slopes[1] = xzslope(Verts[1], Verts[2]);
  216.   Slopes[2] = xzslope(Verts[2], Verts[0]);
  217.  
  218.   lengths[0] = avglen;          
  219.   for (i = 1; i < Level; i++) {   
  220.     lengths[i] = lengths[i-1]/2;     /* compute edge length for each level */
  221.   }
  222.  
  223.   for (i = 0; i < Level; i++) {     /* DispFactor and DispBias arrays */      
  224.     DispFactor[i] = (lengths[i] * ((i <= 7) ? fraction[i] : fraction[7]));
  225.     DispBias[i]   = ((i <= 7) ? bias[i] : bias[7]);
  226.   } 
  227.  
  228.   glBegin(GL_TRIANGLES);
  229.     FMR(v1, v2, v3, 0);    /* issues no GL but vertex calls */
  230.   glEnd();
  231. }
  232.  
  233.  /*
  234.   * draw a mountain and build the display list
  235.   */
  236. void CreateMountain(void)
  237. {
  238.   GLfloat v1[3] = { 0, 0, -1 }, v2[3] = { -1, 0, 1 }, v3[3] = { 1, 0, 1 };
  239.   int pegged[3] = { 1, 1, 1 };
  240.  
  241.   glNewList(MOUNTAIN, GL_COMPILE);
  242.   glPushAttrib(GL_LIGHTING_BIT);
  243.     glCallList(MOUNTAIN_MAT);
  244.     FractalMountain(v1, v2, v3, pegged);
  245.   glPopAttrib();
  246.   glEndList();
  247. }
  248.  
  249.   /*
  250.    * new random numbers to make a different moutain
  251.    */
  252. void NewMountain(void)
  253. {
  254.   InitRandTable(time(NULL));
  255. }
  256.  
  257. /***************************************************************/
  258. /***************************** TREE ****************************/
  259. /***************************************************************/
  260.  
  261. long TreeSeed;   /* for srand48 - remember so we can build "same tree"
  262.                      at a different level */
  263.  
  264.  /*
  265.   * recursive tree drawing thing, fleshed out from class notes pseudocode 
  266.   */
  267. void FractalTree(int level)
  268. {
  269.   long savedseed;  /* need to save seeds while building tree too */
  270.  
  271.   if (level == Level) {
  272.       glPushMatrix();
  273.         glRotatef(drand48()*180, 0, 1, 0);
  274.         glCallList(STEMANDLEAVES);
  275.       glPopMatrix();
  276.   } else {
  277.     glCallList(STEM);
  278.     glPushMatrix();
  279.     glRotatef(drand48()*180, 0, 1, 0);
  280.     glTranslatef(0, 1, 0);
  281.     glScalef(0.7, 0.7, 0.7);
  282.  
  283.       savedseed = (long) drand48()*ULONG_MAX;    /* recurse on a 3-way branching */
  284.       glPushMatrix();    
  285.         glRotatef(110 + drand48()*40, 0, 1, 0);
  286.         glRotatef(30 + drand48()*20, 0, 0, 1);
  287.         FractalTree(level + 1);
  288.       glPopMatrix();
  289.  
  290.       srand48(savedseed);
  291.       savedseed = (long) drand48()*ULONG_MAX;
  292.       glPushMatrix();
  293.         glRotatef(-130 + drand48()*40, 0, 1, 0);
  294.         glRotatef(30 + drand48()*20, 0, 0, 1);
  295.         FractalTree(level + 1);
  296.       glPopMatrix();
  297.  
  298.       srand48(savedseed);
  299.       glPushMatrix();
  300.         glRotatef(-20 + drand48()*40, 0, 1, 0);
  301.         glRotatef(30 + drand48()*20, 0, 0, 1);
  302.         FractalTree(level + 1);
  303.       glPopMatrix();
  304.  
  305.     glPopMatrix();
  306.   }
  307. }
  308.  
  309.   /*
  310.    * Create display lists for a leaf, a set of leaves, and a stem
  311.    */
  312. void CreateTreeLists(void)
  313. {
  314.   GLUquadricObj *cylquad = gluNewQuadric();
  315.   int i;
  316.  
  317.   glNewList(STEM, GL_COMPILE);
  318.   glPushMatrix();
  319.     glRotatef(-90, 1, 0, 0);
  320.     gluCylinder(cylquad, 0.1, 0.08, 1, 10, 2 );
  321.   glPopMatrix();
  322.   glEndList();
  323.  
  324.   glNewList(LEAF, GL_COMPILE);  /* I think this was jeff allen's leaf idea */
  325.     glBegin(GL_TRIANGLES);
  326.       glNormal3f(-0.1, 0, 0.25);  /* not normalized */
  327.       glVertex3f(0, 0, 0);
  328.       glVertex3f(0.25, 0.25, 0.1);
  329.       glVertex3f(0, 0.5, 0);
  330.  
  331.       glNormal3f(0.1, 0, 0.25);
  332.       glVertex3f(0, 0, 0);
  333.       glVertex3f(0, 0.5, 0);
  334.       glVertex3f(-0.25, 0.25, 0.1);
  335.     glEnd();
  336.   glEndList();
  337.  
  338.   glNewList(STEMANDLEAVES, GL_COMPILE);
  339.   glPushMatrix();
  340.   glPushAttrib(GL_LIGHTING_BIT);
  341.     glCallList(STEM);
  342.     glCallList(LEAF_MAT);
  343.     for(i = 0; i < 3; i++) {
  344.       glTranslatef(0, 0.333, 0);
  345.       glRotatef(90, 0, 1, 0);
  346.       glPushMatrix();
  347.         glRotatef(0, 0, 1, 0);
  348.         glRotatef(50, 1, 0, 0);
  349.         glCallList(LEAF);
  350.       glPopMatrix();
  351.       glPushMatrix();
  352.         glRotatef(180, 0, 1, 0);
  353.         glRotatef(60, 1, 0, 0);
  354.         glCallList(LEAF);
  355.       glPopMatrix();
  356.     }
  357.   glPopAttrib();
  358.   glPopMatrix();
  359.   glEndList();
  360. }
  361.  
  362.  /*
  363.   * draw and build display list for tree
  364.   */
  365. void CreateTree(void)
  366. {
  367.   srand48(TreeSeed);
  368.  
  369.   glNewList(TREE, GL_COMPILE);
  370.     glPushMatrix();
  371.     glPushAttrib(GL_LIGHTING_BIT);
  372.     glCallList(TREE_MAT);
  373.     glTranslatef(0, -1, 0);
  374.     FractalTree(0);
  375.     glPopAttrib();
  376.     glPopMatrix();
  377.   glEndList();  
  378. }
  379.  
  380.  /*
  381.   * new seed for a new tree (groan)
  382.   */
  383. void NewTree(void)
  384. {
  385.   TreeSeed = time(NULL);
  386. }
  387.  
  388. /***************************************************************/
  389. /*********************** FRACTAL PLANET ************************/
  390. /***************************************************************/
  391.  
  392. void CreateIsland(void)
  393. {
  394.   CreateMountain();
  395.   glNewList(ISLAND, GL_COMPILE);
  396.   glPushAttrib(GL_LIGHTING_BIT);
  397.   glMatrixMode(GL_MODELVIEW);
  398.   glPushMatrix();
  399.     glCallList(WATER_MAT);
  400.  
  401.     glBegin(GL_QUADS);
  402.       glNormal3f(0, 1, 0);
  403.       glVertex3f(100, 0.01, 100);
  404.       glVertex3f(100, 0.01, -100);
  405.       glVertex3f(-100, 0.01, -100);
  406.       glVertex3f(-100, 0.01, 100);
  407.     glEnd();
  408.  
  409.     glPushMatrix();
  410.     glTranslatef(0, -0.1, 0);
  411.     glCallList(MOUNTAIN);
  412.     glPopMatrix();
  413.  
  414.     glPushMatrix();
  415.     glRotatef(135, 0, 1, 0);
  416.     glTranslatef(0.2, -0.15, -0.4);
  417.     glCallList(MOUNTAIN);
  418.     glPopMatrix();
  419.  
  420.     glPushMatrix();
  421.     glRotatef(-60, 0, 1, 0);
  422.     glTranslatef(0.7, -0.07, 0.5);
  423.     glCallList(MOUNTAIN);
  424.     glPopMatrix();
  425.  
  426.     glPushMatrix();
  427.     glRotatef(-175, 0, 1, 0);
  428.     glTranslatef(-0.7, -0.05, -0.5);
  429.     glCallList(MOUNTAIN);
  430.     glPopMatrix();
  431.  
  432.     glPushMatrix();
  433.     glRotatef(165, 0, 1, 0);
  434.     glTranslatef(-0.9, -0.12, 0.0);
  435.     glCallList(MOUNTAIN);
  436.     glPopMatrix();
  437.  
  438.   glPopMatrix();
  439.   glPopAttrib();
  440.   glEndList();  
  441. }
  442.  
  443.  
  444. void NewFractals(void)
  445. {
  446.   NewMountain();
  447.   NewTree();
  448. }
  449.  
  450. void Create(int fract)
  451. {
  452.   switch(fract) {
  453.     case MOUNTAIN:
  454.       CreateMountain();
  455.       break;
  456.     case TREE:
  457.       CreateTree();
  458.       break;
  459.     case ISLAND:
  460.       CreateIsland();
  461.       break;
  462.   }
  463. }
  464.  
  465.  
  466.  
  467. /***************************************************************/
  468. /**************************** OPENGL ***************************/
  469. /***************************************************************/
  470.  
  471.  
  472. void SetupMaterials(void)
  473. {
  474.   GLfloat mtn_ambuse[] =   { 0.426, 0.256, 0.108, 1.0 };
  475.   GLfloat mtn_specular[] = { 0.394, 0.272, 0.167, 1.0 };
  476.   GLfloat mtn_shininess[] = { 10 };
  477.  
  478.   GLfloat water_ambuse[] =   { 0.0, 0.1, 0.5, 1.0 };
  479.   GLfloat water_specular[] = { 0.0, 0.1, 0.5, 1.0 };
  480.   GLfloat water_shininess[] = { 10 };
  481.  
  482.   GLfloat tree_ambuse[] =   { 0.4, 0.25, 0.1, 1.0 };
  483.   GLfloat tree_specular[] = { 0.0, 0.0, 0.0, 1.0 };
  484.   GLfloat tree_shininess[] = { 0 };
  485.  
  486.   GLfloat leaf_ambuse[] =   { 0.0, 0.8, 0.0, 1.0 };
  487.   GLfloat leaf_specular[] = { 0.0, 0.8, 0.0, 1.0 };
  488.   GLfloat leaf_shininess[] = { 10 };
  489.  
  490.   glNewList(MOUNTAIN_MAT, GL_COMPILE);
  491.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mtn_ambuse);
  492.     glMaterialfv(GL_FRONT, GL_SPECULAR, mtn_specular);
  493.     glMaterialfv(GL_FRONT, GL_SHININESS, mtn_shininess);
  494.   glEndList();
  495.  
  496.   glNewList(WATER_MAT, GL_COMPILE);
  497.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, water_ambuse);
  498.     glMaterialfv(GL_FRONT, GL_SPECULAR, water_specular);
  499.     glMaterialfv(GL_FRONT, GL_SHININESS, water_shininess);
  500.   glEndList();
  501.  
  502.   glNewList(TREE_MAT, GL_COMPILE);
  503.     glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, tree_ambuse);
  504.     glMaterialfv(GL_FRONT, GL_SPECULAR, tree_specular);
  505.     glMaterialfv(GL_FRONT, GL_SHININESS, tree_shininess);
  506.   glEndList();
  507.  
  508.   glNewList(LEAF_MAT, GL_COMPILE);
  509.     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, leaf_ambuse);
  510.     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, leaf_specular);
  511.     glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, leaf_shininess);
  512.   glEndList();
  513. }
  514.  
  515. void myGLInit(void)
  516. {
  517.   GLfloat light_ambient[] = { 0.0, 0.0, 0.0, 1.0 };
  518.   GLfloat light_diffuse[] = { 1.0, 1.0, 1.0, 1.0 };
  519.   GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
  520.   GLfloat light_position[] = { 0.0, 0.3, 0.3, 0.0 };
  521.  
  522.   GLfloat lmodel_ambient[] = { 0.4, 0.4, 0.4, 1.0 };
  523.  
  524.   glLightfv(GL_LIGHT0, GL_AMBIENT, light_ambient);
  525.   glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  526.   glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular);
  527.   glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  528.     
  529.   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient);
  530.  
  531.   glEnable(GL_LIGHTING);
  532.   glEnable(GL_LIGHT0);
  533.  
  534.   glDepthFunc(GL_LEQUAL);
  535.   glEnable(GL_DEPTH_TEST);
  536.  
  537.   glEnable(GL_NORMALIZE);
  538. #if 0
  539.   glEnable(GL_CULL_FACE);
  540.   glCullFace(GL_BACK);
  541. #endif
  542.  
  543.   glShadeModel(GL_SMOOTH);
  544. #if 0
  545.   glEnable(GL_BLEND);
  546.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  547. #endif
  548.  
  549.   SetupMaterials();
  550.   CreateTreeLists();
  551.  
  552.   glFlush();
  553.  
  554. /***************************************************************/
  555. /************************ GLUT STUFF ***************************/
  556. /***************************************************************/
  557.  
  558. void reshape(GLsizei w, GLsizei h)
  559. {
  560.   glViewport(0,0,w,h);
  561.   glMatrixMode(GL_PROJECTION);
  562.   glLoadIdentity();
  563.   gluPerspective(60.0, (GLdouble)w/h, 0.01, 100);
  564.   glPushMatrix();
  565.   glMatrixMode(GL_MODELVIEW);
  566.   glFlush();
  567. }
  568.  
  569. void display(void)
  570.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  571.   glFlush();
  572.  
  573.   glMatrixMode(GL_PROJECTION);
  574.   glPopMatrix();
  575.   glPushMatrix();  /* clear of last viewing xform, leaving perspective */
  576.  
  577.   agvViewTransform();
  578.  
  579.   glMatrixMode(GL_MODELVIEW);
  580.   glLoadIdentity();
  581.  
  582.   if (Rebuild) {
  583.     Create(Fract);
  584.     Rebuild = 0;
  585.   }
  586.  
  587.   glCallList(Fract);
  588.  
  589.   if (DrawAxes)
  590.     glCallList(AXES);
  591.  
  592.   glutSwapBuffers();
  593.   glFlush();
  594. }
  595.  
  596.  
  597. void visible(int v)
  598. {
  599.   if (v == GLUT_VISIBLE)
  600.     agvSetAllowIdle(1);
  601.   else {
  602.     glutIdleFunc(NULL);
  603.     agvSetAllowIdle(0);
  604.   }
  605. }
  606.  
  607. void menuuse(int v)
  608. {
  609.   if (v == GLUT_MENU_NOT_IN_USE)
  610.     agvSetAllowIdle(1);
  611.   else {
  612.     glutIdleFunc(NULL);
  613.     agvSetAllowIdle(0);
  614.   }
  615. }
  616.  
  617. /***************************************************************/
  618. /******************* MENU SETUP & HANDLING *********************/
  619. /***************************************************************/
  620.  
  621. typedef enum { MENU_QUIT, MENU_RAND, MENU_MOVE, MENU_AXES } MenuChoices;
  622.  
  623. void setlevel(int value)
  624. {
  625.   Level = value;
  626.   Rebuild = 1;
  627.   glutPostRedisplay();
  628. }
  629.  
  630. void choosefract(int value)
  631. {
  632.   Fract = value;
  633.   Rebuild = 1;
  634.   glutPostRedisplay();
  635. }
  636.  
  637. void handlemenu(int value)
  638. {
  639.   switch (value) {
  640.     case MENU_QUIT:
  641.       exit(0);
  642.       break;
  643.     case MENU_RAND:
  644.       NewFractals();
  645.       Rebuild = 1;
  646.       glutPostRedisplay();
  647.       break;
  648.     case MENU_AXES:
  649.       DrawAxes = !DrawAxes;
  650.       glutPostRedisplay();
  651.       break;
  652.     }
  653. }
  654.  
  655. void MenuInit(void)
  656. {
  657.   int submenu3, submenu2, submenu1;
  658.  
  659.   submenu1 = glutCreateMenu(setlevel);
  660.   glutAddMenuEntry("0", 0);  glutAddMenuEntry("1", 1);
  661.   glutAddMenuEntry("2", 2);  glutAddMenuEntry("3", 3);
  662.   glutAddMenuEntry("4", 4);  glutAddMenuEntry("5", 5);
  663.   glutAddMenuEntry("6", 6);  glutAddMenuEntry("7", 7);
  664.   glutAddMenuEntry("8", 8);
  665.  
  666.   submenu2 = glutCreateMenu(choosefract);
  667.   glutAddMenuEntry("Moutain", MOUNTAIN);
  668.   glutAddMenuEntry("Tree", TREE);
  669.   glutAddMenuEntry("Island", ISLAND);
  670.  
  671.   submenu3 = glutCreateMenu(agvSwitchMoveMode);
  672.   glutAddMenuEntry("Flying", FLYING);
  673.   glutAddMenuEntry("Polar", POLAR);
  674.  
  675.   glutCreateMenu(handlemenu);
  676.   glutAddSubMenu("Level", submenu1);
  677.   glutAddSubMenu("Fractal", submenu2);
  678.   glutAddSubMenu("Movement", submenu3);
  679.   glutAddMenuEntry("New Fractal",      MENU_RAND);
  680.   glutAddMenuEntry("Toggle Axes", MENU_AXES);
  681.   glutAddMenuEntry("Quit",             MENU_QUIT);
  682.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  683. }
  684.  
  685.  
  686. /***************************************************************/
  687. /**************************** MAIN *****************************/
  688. /***************************************************************/
  689.  
  690. int main(int argc, char** argv)
  691. {
  692.   glutInit(&argc, argv);
  693.   glutInitWindowSize(512, 512);
  694.   glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE);
  695.   glutCreateWindow("Fractal Planet?");
  696.  
  697.   agvInit(1); /* 1 cause we don't have our own idle */
  698.  
  699.   glutReshapeFunc(reshape);
  700.   glutDisplayFunc(display);
  701.   glutVisibilityFunc(visible);
  702.   glutMenuStateFunc(menuuse);
  703.  
  704.   NewFractals();
  705.   agvMakeAxesList(AXES);
  706.   myGLInit(); 
  707.   MenuInit();
  708.  
  709.   glutMainLoop();
  710.   return 0;             /* ANSI C requires main to return int. */
  711. }
  712.